﻿/*
 * This file is part of MonoStrategy.
 *
 * Copyright (C) 2010-2011 Christoph Husse
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors: 
 *      # Christoph Husse
 * 
 * Also checkout our homepage: http://monostrategy.codeplex.com/
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MonoStrategy.RenderSystem;

namespace MonoStrategy
{
    public class VisualWorkingArea : PositionTracker
    {
        private List<RenderableAnimationClass> m_Visuals = new List<RenderableAnimationClass>();
        private List<CyclePoint> m_VisualPositions = new List<CyclePoint>();

        public TerrainRenderer Renderer { get; private set; }
        public Int32 Radius { get; private set; }

        public VisualWorkingArea(TerrainRenderer inRenderer, Point inCenter, Int32 inRadius) 
        {
            if (inRenderer == null)
                throw new ArgumentNullException();

            Position = CyclePoint.FromGrid(inCenter);
            Radius = inRadius;
            Renderer = inRenderer;

            Procedure<Point, String> handler = (pos, animSet) =>
            {
                var anim = Renderer.CreateAnimation("Other", new PositionTracker() { Position = CyclePoint.FromGrid(pos) });

                anim.Play(animSet);

                m_Visuals.Add(anim);
                m_VisualPositions.Add(anim.Position);

                if ((pos.X < 0) || (pos.Y < 0) || (pos.X >= Renderer.Size) || (pos.Y >= Renderer.Size))
                    anim.IsVisible = false;
            };

            int[] markerRadius;
            double step, radius;

            if (inRadius > 4)
            {
                if (inRadius > 8)
                {
                    if (inRadius > 12)
                        markerRadius = new int[4];
                    else
                        markerRadius = new int[3];
                }else
                    markerRadius = new int[2];
            }else
                markerRadius = new int[1];

            step = inRadius / (double)markerRadius.Length;
            radius = step;

            for (int i = 0; i < markerRadius.Length; i++)
            {
                GridSearch.GridCircleAround(inCenter, Renderer.Size, Renderer.Size, (int)radius, i + 1, (pos) => { handler(pos, "AreaMarker" + (markerRadius.Length - i)); });

                radius += step;
            }

            OnPositionChanged += (sender, oldValue, newValue) =>
            {
                for(int i = 0; i < m_Visuals.Count; i++)
                {
                    var visual = m_Visuals[i];
                    CyclePoint newPos = CyclePoint.FromGrid(
                        m_VisualPositions[i].X + newValue.X - oldValue.X,
                        m_VisualPositions[i].Y + newValue.Y - oldValue.Y);

                    if ((newPos.X < 0) || (newPos.Y < 0) || (newPos.X >= Renderer.Size) || (newPos.Y >= Renderer.Size))
                        visual.IsVisible = false;
                    else
                    {
                        visual.IsVisible = true;
                        visual.Position = newPos;
                    }

                    m_VisualPositions[i] = newPos;
                }
            };
        }

        public void Dispose()
        {
            foreach (var visual in m_Visuals)
            {
                Renderer.RemoveVisual(visual);
            }

            m_Visuals.Clear();
        }
    }
}
